ngl: Make the coloring shader more versatile
authorMatthias Clasen <mclasen@redhat.com>
Fri, 12 Mar 2021 06:27:19 +0000 (01:27 -0500)
committerMatthias Clasen <mclasen@redhat.com>
Fri, 12 Mar 2021 18:19:37 +0000 (13:19 -0500)
When the color passed is transparent black, use
the color from the texture as source, instead of
as mask. This lets use use the coloring program
both for regular and color glyphs, avoiding
program changes in text with Emoji.

gsk/ngl/gsknglrenderjob.c
gsk/ngl/resources/coloring.glsl

index 14e3b3e42b80d36168401029224b740648659e3e..8f675755643e37b7488ae4684d5f43be42806ca3 100644 (file)
@@ -2703,15 +2703,20 @@ gsk_ngl_render_job_visit_text_node (GskNglRenderJob     *job,
   guint last_texture = 0;
   GskNglDrawVertex *vertices;
   guint used = 0;
+  GdkRGBA c;
 
   if (num_glyphs == 0)
     return;
 
-  /* If the font has color glyphs, we don't need to recolor anything */
+  program = CHOOSE_PROGRAM (job, coloring);
+
+  /* If the font has color glyphs, we don't need to recolor anything.
+   * We tell the shader by setting the color to vec4(-1).
+   */
   if (!force_color && gsk_text_node_has_color_glyphs (node))
-    program = CHOOSE_PROGRAM (job, blit);
+    c = (GdkRGBA) { -1.f, -1.f, -1.f, -1.f };
   else
-    program = CHOOSE_PROGRAM (job, coloring);
+    c = *color;
 
   lookup.font = (PangoFont *)font;
   lookup.scale = (guint) (text_scale * 1024);
@@ -2786,55 +2791,55 @@ gsk_ngl_render_job_visit_text_node (GskNglRenderJob     *job,
       vertices[base+0].position[1] = glyph_y;
       vertices[base+0].uv[0] = tx;
       vertices[base+0].uv[1] = ty;
-      vertices[base+0].color[0] = color->red;
-      vertices[base+0].color[1] = color->green;
-      vertices[base+0].color[2] = color->blue;
-      vertices[base+0].color[3] = color->alpha;
+      vertices[base+0].color[0] = c.red;
+      vertices[base+0].color[1] = c.green;
+      vertices[base+0].color[2] = c.blue;
+      vertices[base+0].color[3] = c.alpha;
 
       vertices[base+1].position[0] = glyph_x;
       vertices[base+1].position[1] = glyph_y2;
       vertices[base+1].uv[0] = tx;
       vertices[base+1].uv[1] = ty2;
-      vertices[base+1].color[0] = color->red;
-      vertices[base+1].color[1] = color->green;
-      vertices[base+1].color[2] = color->blue;
-      vertices[base+1].color[3] = color->alpha;
+      vertices[base+1].color[0] = c.red;
+      vertices[base+1].color[1] = c.green;
+      vertices[base+1].color[2] = c.blue;
+      vertices[base+1].color[3] = c.alpha;
 
       vertices[base+2].position[0] = glyph_x2;
       vertices[base+2].position[1] = glyph_y;
       vertices[base+2].uv[0] = tx2;
       vertices[base+2].uv[1] = ty;
-      vertices[base+2].color[0] = color->red;
-      vertices[base+2].color[1] = color->green;
-      vertices[base+2].color[2] = color->blue;
-      vertices[base+2].color[3] = color->alpha;
+      vertices[base+2].color[0] = c.red;
+      vertices[base+2].color[1] = c.green;
+      vertices[base+2].color[2] = c.blue;
+      vertices[base+2].color[3] = c.alpha;
 
       vertices[base+3].position[0] = glyph_x2;
       vertices[base+3].position[1] = glyph_y2;
       vertices[base+3].uv[0] = tx2;
       vertices[base+3].uv[1] = ty2;
-      vertices[base+3].color[0] = color->red;
-      vertices[base+3].color[1] = color->green;
-      vertices[base+3].color[2] = color->blue;
-      vertices[base+3].color[3] = color->alpha;
+      vertices[base+3].color[0] = c.red;
+      vertices[base+3].color[1] = c.green;
+      vertices[base+3].color[2] = c.blue;
+      vertices[base+3].color[3] = c.alpha;
 
       vertices[base+4].position[0] = glyph_x;
       vertices[base+4].position[1] = glyph_y2;
       vertices[base+4].uv[0] = tx;
       vertices[base+4].uv[1] = ty2;
-      vertices[base+4].color[0] = color->red;
-      vertices[base+4].color[1] = color->green;
-      vertices[base+4].color[2] = color->blue;
-      vertices[base+4].color[3] = color->alpha;
+      vertices[base+4].color[0] = c.red;
+      vertices[base+4].color[1] = c.green;
+      vertices[base+4].color[2] = c.blue;
+      vertices[base+4].color[3] = c.alpha;
 
       vertices[base+5].position[0] = glyph_x2;
       vertices[base+5].position[1] = glyph_y;
       vertices[base+5].uv[0] = tx2;
       vertices[base+5].uv[1] = ty;
-      vertices[base+5].color[0] = color->red;
-      vertices[base+5].color[1] = color->green;
-      vertices[base+5].color[2] = color->blue;
-      vertices[base+5].color[3] = color->alpha;
+      vertices[base+5].color[0] = c.red;
+      vertices[base+5].color[1] = c.green;
+      vertices[base+5].color[2] = c.blue;
+      vertices[base+5].color[3] = c.alpha;
 
       batch->draw.vbo_count += GSK_NGL_N_VERTICES;
       used++;
index b6af0c1766b7d281569515a4edbdad28363dd205..d7d2aed7d679f428a3caa1e65aca65361c7b24cc 100644 (file)
@@ -1,20 +1,33 @@
 // VERTEX_SHADER:
 _OUT_ vec4 final_color;
+flat _OUT_ int use_color;
 
 void main() {
   gl_Position = u_projection * u_modelview * vec4(aPosition, 0.0, 1.0);
 
   vUv = vec2(aUv.x, aUv.y);
 
+  // We use this shader for both plain glyphs (used as mask)
+  // and color glpyhs (used as source). The renderer sets
+  // aColor to vec4(-1) for color glyhs.
+  if (distance(aColor, vec4(-1)) < 0.001)
+    use_color = 0;
+  else
+    use_color = 1;
+
   final_color = gsk_premultiply(aColor) * u_alpha;
 }
 
 // FRAGMENT_SHADER:
 
 _IN_ vec4 final_color;
+flat _IN_ int use_color;
 
 void main() {
   vec4 diffuse = GskTexture(u_source, vUv);
 
-  gskSetOutputColor(final_color * diffuse.a);
+  if (use_color == 1)
+    gskSetOutputColor(final_color * diffuse.a);
+  else
+    gskSetOutputColor(diffuse * u_alpha);
 }